#region Using Directives

using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using ScintillaNET;
using WeifenLuo.WinFormsUI.Docking;
using System.Reflection;
using System.Globalization;
using System.Xml;
using System.Linq.Expressions;
using System.Diagnostics;
using System.Xml.Linq;

#endregion Using Directives


namespace TEdit
{
    internal sealed partial class MainForm : Form
    {
        #region Constants

        private const string NEW_DOCUMENT_TEXT = "Untitled";
        private const int LINE_NUMBERS_MARGIN_WIDTH = 35; // TODO Don't hardcode this

        #endregion Constants


        #region Fields
        Encoding_Table et;
        OutputForm m_output;
        FolderForm fld_form;
        private int _newDocumentCount = 0;
        private int _zoomLevel;
        private static string strLoc = Assembly.GetExecutingAssembly().Location;
        public string[] Args;
        public List<Area> Areas = new List<Area>();
        FileInfo fi;
        #endregion Fields


        #region Methods

        private void MainForm_Load(object sender, EventArgs e)
        {
            fi = new FileInfo(strLoc); // get tedit directory

            // The single-instance code is going to save the command line arguments
            // in this member variable before opening the first instance of the app.
            if (this.Args != null)
            {
                ProcessParameters(null, this.Args);
                this.Args = null;
            }

            et = new Encoding_Table();
            m_output = new OutputForm();
            et.Show(dockPanel, DockState.DockRightAutoHide);
            m_output.Show(dockPanel, DockState.DockBottomAutoHide);
            et.listBox1.DoubleClick += new EventHandler(listBox1_DoubleClick);
            fld_form = new FolderForm();
            fld_form.Show(dockPanel, DockState.DockLeftAutoHide);
            fld_form.fileListBox1.MouseDoubleClick += new MouseEventHandler(fileListBox1_MouseDoubleClick);
            Read_Env_file();
            update_Env_List();
        }

        void fileListBox1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            OpenFile(fld_form.fileListBox1.Path + "\\" + fld_form.fileListBox1.FileName);
        }

        public delegate void ProcessParametersDelegate(object sender, string[] args);
        public void ProcessParameters(object sender, string[] args)
        {
            // The form has loaded, and initialization will have been be done.

            // Add the command-line arguments
            if (args != null && args.Length != 0)
            {
                // Open the document specified on the command line
                FileInfo fi = new FileInfo(args[0]);
                if (fi.Exists)
                    OpenFile(fi.FullName);
            }
            else
            {
                // Create a new document
                NewDocument();
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutForm aboutForm = new AboutForm();
            aboutForm.ShowDialog(this);
        }


        private void autoCompleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.AutoComplete.Show();
        }


        private void clearBookmarksToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Markers.DeleteAll(0);
        }


        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Close();
        }


        private void collectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.DropMarkers.Collect();
        }


        private void commentLineToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LineComment);
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Clipboard.Copy();
        }

        private void cutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Clipboard.Cut();
        }

        private void csToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetLanguage("cs");
        }

        private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
        {
            // Update the main form _text to show the current document
            if (ActiveDocument != null)
                this.Text = String.Format(CultureInfo.CurrentCulture, "{0} - {1}", ActiveDocument.Text, Program.Title);
            else
                this.Text = Program.Title;
        }


        private void dropToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.DropMarkers.Drop();
        }


        private void endOfLineToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle EOL visibility for all open files
            endOfLineToolStripMenuItem.Checked = !endOfLineToolStripMenuItem.Checked;
            foreach (DocumentForm doc in dockPanel.Documents)
            {
                doc.Scintilla.EndOfLine.IsVisible = endOfLineToolStripMenuItem.Checked;
            }
        }


        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }


        private void exportAsHtmlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.ExportAsHtml();
        }


        private void findInFilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Coming someday...
        }


        private void findToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.FindReplace.ShowFind();
        }


        private void foldAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
            {
                foreach (Line l in ActiveDocument.Scintilla.Lines)
                {
                    l.FoldExpanded = true;
                }
            }
        }


        private void foldLevelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Lines.Current.FoldExpanded = true;
        }


        private void goToToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.GoTo.ShowGoToDialog();
        }

        private void insertSnippetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Snippets.ShowSnippetList();
        }


        private void lineNumbersToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle the line numbers margin for all documents
            lineNumbersToolStripMenuItem.Checked = !lineNumbersToolStripMenuItem.Checked;
            foreach (DocumentForm docForm in dockPanel.Documents)
            {
                if (lineNumbersToolStripMenuItem.Checked)
                    docForm.Scintilla.Margins.Margin0.Width = LINE_NUMBERS_MARGIN_WIDTH;
                else
                    docForm.Scintilla.Margins.Margin0.Width = 0;
            }
        }

        void listBox1_DoubleClick(object sender, EventArgs e)
        {
            int i = et.listBox1.SelectedIndex;
            if (i > 0)
                ActiveDocument.Scintilla.InsertText(((char)(i - 1)).ToString());
        }


        private void makeLowerCaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LowerCase);
        }

        private void makeUpperCaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.UpperCase);
        }

        private void navigateBackwardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.DocumentNavigation.NavigateBackward();
        }

        private void navigateForwardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.DocumentNavigation.NavigateForward();
        }


        private DocumentForm NewDocument()
        {
            DocumentForm doc = new DocumentForm();
            char[] test = doc.Scintilla.Lexing.WordChars.ToArray();
            doc.Scintilla.SelectionChanged += new EventHandler(Scintilla_SelectionChanged);
            doc.Scintilla.KeyPress += new KeyPressEventHandler(Scintilla_KeyPress);
            doc.closeAllButThisToolStripMenuItem.Click += new EventHandler(closeAllButThisToolStripMenuItem_Click);
            doc.closeAllToolStripMenuItem.Click += new EventHandler(closeAllToolStripMenuItem_Click);

            SetScintillaToCurrentOptions(doc);
            doc.Text = String.Format(CultureInfo.CurrentCulture, "{0}{1}", NEW_DOCUMENT_TEXT, ++_newDocumentCount);
            doc.Show(dockPanel);

            SetLanguage("InfoBasic");   // kvk
            return doc;
        }

        void Scintilla_KeyPress(object sender, KeyPressEventArgs e)
        {
            toolLinepos.Text = ActiveDocument.Scintilla.Caret.LineNumber.ToString();
            toolColpos.Text = ActiveDocument.Scintilla.Caret.Position.ToString();
        }

        void Scintilla_SelectionChanged(object sender, EventArgs e)
        {
            toolSellen.Text = ActiveDocument.Scintilla.Selection.Length.ToString();
        }

        void closeAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            closeAll();
        }

        void closeAll()
        {
            while (dockPanel.DocumentsCount > 0)
                ActiveDocument.Close();
        }

        void closeAllButThisToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DocumentForm[] docs = new DocumentForm[dockPanel.DocumentsCount - 1];
            int i = 0;
            foreach (DocumentForm doc in dockPanel.Documents)
            {
                if (doc != ActiveDocument)
                    docs[i++] = doc;
            }
            while (--i >= 0)
            {
                docs[i].Close();
            }
        }


        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewDocument();
        }


        private void nextBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //	 I've got to redo this whole FindNextMarker/FindPreviousMarker Scheme
            Line l = ActiveDocument.Scintilla.Lines.Current.FindNextMarker(1);
            if (l != null)
                l.Goto();
        }


        private void OpenFile()
        {
            if (openFileDialog.ShowDialog() != DialogResult.OK)
                return;

            foreach (string filePath in openFileDialog.FileNames)
            {
                // Ensure this file isn't already open
                bool isOpen = false;
                foreach (DocumentForm documentForm in dockPanel.Documents)
                {
                    if (filePath.Equals(documentForm.FilePath, StringComparison.OrdinalIgnoreCase))
                    {
                        documentForm.Select();
                        isOpen = true;
                        break;
                    }
                }

                // Open the files
                if (!isOpen)
                    OpenFile(filePath);
            }
        }


        private void OpenFile(string filePath)
        {
            foreach (DocumentForm d in dockPanel.Documents)
            {
                if (d.FilePath == filePath)
                {
                    d.Focus();
                    return;
                }
            }

            DocumentForm doc = NewDocument();

            doc.Scintilla.AppendText(File.ReadAllText(filePath));
            doc.Scintilla.UndoRedo.EmptyUndoBuffer();
            doc.Scintilla.Modified = false;
            doc.Text = Path.GetFileName(filePath);
            doc.FilePath = filePath;
            doc.Show(dockPanel);

            FileInfo fi = new FileInfo(filePath);
            if (fi.Extension == ".xml" || fi.Extension == ".html")
                SetLanguage("xml");
            else if (fi.Extension == ".java" || fi.Extension == ".cs")
                SetLanguage("cs");
            else
                SetLanguage("InfoBasic");
        }


        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFile();
        }


        private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Clipboard.Paste();
        }


        private void plainTextToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetLanguage(String.Empty);
        }


        private void previosBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //	 I've got to redo this whole FindNextMarker/FindPreviousMarker Scheme
            Line l = ActiveDocument.Scintilla.Lines.Current.FindPreviousMarker(1);
            if (l != null)
                l.Goto();
        }


        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Printing.PrintPreview();
        }


        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Printing.Print();
        }

        private void redoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.UndoRedo.Redo();
        }


        private void replaceInFilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //	Coming someday...
        }


        private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.FindReplace.ShowReplace();
        }


        private void resetZoomToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _zoomLevel = 0;
            UpdateAllScintillaZoom();
        }


        private void saveAllStripMenuItem_Click(object sender, EventArgs e)
        {
            foreach (DocumentForm doc in dockPanel.Documents)
            {
                doc.Activate();
                doc.Save();
            }
        }


        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.SaveAs();
        }


        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Save();
        }


        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Selection.SelectAll();
        }


        private void SetLanguage(string language)
        {
            // Use a built-in lexer and configuration

            if (language == "InfoBasic")
            {
                ActiveDocument.Scintilla.ConfigurationManager.CustomLocation = fi.DirectoryName;
            }
            else
                ActiveDocument.Scintilla.ConfigurationManager.CustomLocation = string.Empty;


            ActiveDocument.Scintilla.ConfigurationManager.Language = language;

            if ("cs".Equals(language, StringComparison.OrdinalIgnoreCase))
                ActiveDocument.Scintilla.Indentation.SmartIndentType = SmartIndent.CPP; // Smart indenting...
            else
                ActiveDocument.Scintilla.Indentation.SmartIndentType = SmartIndent.None;
        }

        private void SetScintillaToCurrentOptions(DocumentForm doc)
        {
            // Turn on line numbers?
            if (lineNumbersToolStripMenuItem.Checked)
                doc.Scintilla.Margins.Margin0.Width = LINE_NUMBERS_MARGIN_WIDTH;
            else
                doc.Scintilla.Margins.Margin0.Width = 0;

            // Turn on white space?
            if (whitespaceToolStripMenuItem.Checked)
                doc.Scintilla.Whitespace.Mode = WhitespaceMode.VisibleAlways;
            else
                doc.Scintilla.Whitespace.Mode = WhitespaceMode.Invisible;

            // Turn on word wrap?
            if (wordWrapToolStripMenuItem.Checked)
                doc.Scintilla.LineWrapping.Mode = LineWrappingMode.Word;
            else
                doc.Scintilla.LineWrapping.Mode = LineWrappingMode.None;

            // Show EOL?
            doc.Scintilla.EndOfLine.IsVisible = endOfLineToolStripMenuItem.Checked;

            // Set the zoom
            doc.Scintilla.ZoomFactor = _zoomLevel;
        }


        private void statusBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle the visibility of the status strip
            statusStrip.Visible = !statusStrip.Visible;
            statusBarToolStripMenuItem.Checked = statusStrip.Visible;
        }


        private void surroundWithToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Snippets.ShowSnippetList();
        }


        private void toggleBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Line currentLine = ActiveDocument.Scintilla.Lines.Current;
            if (ActiveDocument.Scintilla.Markers.GetMarkerMask(currentLine) == 0)
            {
                currentLine.AddMarker(0);
            }
            else
            {
                currentLine.DeleteMarker(0);
            }
        }


        private void toolBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle the visibility of the tool bar
            toolStrip.Visible = !toolStrip.Visible;
            toolBarToolStripMenuItem.Checked = toolStrip.Visible;
        }


        private void uncommentLineToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LineUncomment);
        }


        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.UndoRedo.Undo();
        }


        private void unfoldAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
            {
                foreach (Line l in ActiveDocument.Scintilla.Lines)
                {
                    l.FoldExpanded = true;
                }
            }
        }


        private void unfoldLevelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Lines.Current.FoldExpanded = false;
        }


        private void UpdateAllScintillaZoom()
        {
            // Update zoom level for all files
            foreach (DocumentForm doc in dockPanel.Documents)
                doc.Scintilla.ZoomFactor = _zoomLevel;
        }


        private void vbScriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetLanguage("vbscript");
        }


        private void whitespaceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle the whitespace mode for all open files
            whitespaceToolStripMenuItem.Checked = !whitespaceToolStripMenuItem.Checked;
            foreach (DocumentForm doc in dockPanel.Documents)
            {
                if (whitespaceToolStripMenuItem.Checked)
                    doc.Scintilla.Whitespace.Mode = WhitespaceMode.VisibleAlways;
                else
                    doc.Scintilla.Whitespace.Mode = WhitespaceMode.Invisible;
            }
        }


        private void wordWrapToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Toggle word wrap for all open files
            wordWrapToolStripMenuItem.Checked = !wordWrapToolStripMenuItem.Checked;
            foreach (DocumentForm doc in dockPanel.Documents)
            {
                if (wordWrapToolStripMenuItem.Checked)
                    doc.Scintilla.LineWrapping.Mode = LineWrappingMode.Word;
                else
                    doc.Scintilla.LineWrapping.Mode = LineWrappingMode.None;
            }
        }


        private void xmlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetLanguage("xml");
        }


        private void zoomInToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Increase the zoom for all open files
            _zoomLevel++;
            UpdateAllScintillaZoom();
        }


        private void zoomOutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _zoomLevel--;
            UpdateAllScintillaZoom();
        }

        #endregion Methods


        #region Properties

        public DocumentForm ActiveDocument
        {
            get
            {
                return dockPanel.ActiveDocument as DocumentForm;
            }
        }

        #endregion Properties


        #region Constructors

        public MainForm()
        {
            // The VS designer doesn't allow the form icon to be specified
            // from a resource, so we'll do it manually here
            this.Icon = Properties.Resources.TEditApp;
            m_DelegateOpenFile = new DelegateOpenFile(this.OpenFile);
            Properties.Settings.Default.TEdit = strLoc;
            InitializeComponent();
        }


        public MainForm(string[] args)
            : this()
        {
            // Store the command line args
            this.Args = args;

            // Set the application title
            Text = Program.Title;
            aboutToolStripMenuItem.Text = String.Format(CultureInfo.CurrentCulture, "&About {0}", Program.Title);
        }

        #endregion Constructors

        private void basicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetLanguage("InfoBasic");
        }

        private void toggleCaseToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ActiveDocument.Scintilla.Selection.Text.ToLower() == ActiveDocument.Scintilla.Selection.Text)
                ActiveDocument.Scintilla.Commands.Execute(BindableCommand.UpperCase);
            else
                ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LowerCase);
        }

        private void CharacterTableMenuItem_Click(object sender, EventArgs e)
        {
            et.Show();
        }

        private delegate void DelegateOpenFile(String s);           // type
        private DelegateOpenFile m_DelegateOpenFile;                // instance

        private void MainForm_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                // When file(s) are dragged from Explorer to the form, IDataObject
                // contains array of file names. If one file is dragged, array contains one element.
                Array a = (Array)e.Data.GetData(DataFormats.FileDrop);
                int i = a.Length;
                string s = "";

                while (i > 0)
                {
                    i--;
                    if (a != null)
                    {
                        // Extract string from first array element
                        s = a.GetValue(i).ToString();

                        // Call OpenFile asynchronously.
                        // Explorer instance from which file is dropped is not responding
                        // all the time when DragDrop handler is active, so we need to return
                        // immidiately (especially if OpenFile shows MessageBox).

                        this.BeginInvoke(m_DelegateOpenFile, new Object[] { s });
                    }
                }
                this.Activate();        // in the case Explorer overlaps this form
            }
            catch (Exception)
            {
                // don't show MessageBox here - Explorer is waiting !
            }
        }

        private void MainForm_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
        }

        #region code review
        private delegate void Do_CodeReview(LineCollection ts);
        private Do_CodeReview m_codereview;
        private void codeReviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LineCollection ts = ActiveDocument.Scintilla.Lines;

            m_codereview = new Do_CodeReview(this.Perform_Code_Review);
            //Thread ts = new Thread(m_codereview);
            //this.BeginInvoke(m_codereview, new object[] { ts });
            m_codereview(ts);

            m_output.Set_output(code_Report);
            // m_error.errList.Items.AddRange(Code_review_errors.ToArray());
        }

        //code review varaibles.
        int para_lines = 0;
        int nest_lvl = 0;
        int nest_lines = 0;
        int line_no = 0;
        bool first_code_line = false;

        const int max_code_lines = 600;
        const int max_para_lines = 100;
        const int max_nest = 3;
        const int max_nest_lines = 40;

        string[] nest_start = new string[] { "FOR", "LOOP", "THEN", "ELSE", "LOCKED", "BEGIN" };
        string[] nest_end = new string[] { "NEXT", "REPEAT", "END" };
        string[] nest_terminators = new string[] { "THEN", "ELSE", "LOCKED" };

        //weightings
        const int W_LABEL = -10;
        const int W_SIZE = 10;
        const int W_COMMENTS = -1;
        const int W_PARA = 5;
        const int W_NEST = 50;
        const int W_NEST_LINES = 5;
        const int W_GOTO = 100;
        const int W_NON_STANDARD = 100;

        // totals
        int T_COMMENT = 0;
        int T_PARA = 0;
        int T_NEST_LINES = 0;
        int T_NEST = 0;
        int T_CODE = 0;
        int T_LABEL = 0;
        int T_GOTO = 0;
        int T_NON_STANDARD = 0;

        string[] code_Report = new string[9];
        List<string> Code_review_errors = new List<string>();

        private void Perform_Code_Review(LineCollection ts)
        {
            T_COMMENT = 0;
            T_PARA = 0;
            T_NEST_LINES = 0;
            T_NEST = 0;
            T_CODE = 0;
            T_LABEL = 0;
            T_GOTO = 0;
            T_NON_STANDARD = 0;
            RATING = 0;
            line_no = 0;

            Code_review_errors.Clear();

            int line_cnt = ts.Count;
            foreach (Line line in ts)
            {
                line_no++;

                string y_line = line.Text.Trim();
                y_line = y_line.Replace("  ", " ");

                if (y_line == "")
                    continue;

                if (y_line[0] == '*' || y_line[0] == '!' || (y_line.Length > 3 && y_line.Substring(0, 3) == "REM"))
                    count_Comments(y_line);
                else
                {
                    Prepare_line(y_line);
                    foreach (string stmt in new_lines)
                    {
                        string STATEMENT = stmt.Trim();
                        if (STATEMENT == "" || STATEMENT == "$INSERT")
                            ;
                        else if (STATEMENT[0] == '*' || STATEMENT[0] == '!' || (STATEMENT.Length > 3 && STATEMENT.Substring(0, 3) == "REM"))
                            count_Comments(STATEMENT);
                        else if (STATEMENT[STATEMENT.Length - 1] == ':')
                            new_label();
                        else if (STATEMENT.Length > 10 && (STATEMENT.Substring(0, 10) == "SUBROUTINE" || STATEMENT.Substring(0, 7) == "PROGRAM"))
                            ;
                        else
                            analyse_code(STATEMENT);
                    }
                }
            }
            finalise_Rating();
            Code_Review_Report();
        }

        int RATING = 0;

        List<string> new_lines = new List<string>();

        private void Prepare_line(string line)
        {
            string OPEN_QUOTE = "";
            string tmp = "";
            new_lines.Clear();
            foreach (char c in line)
            {
                if (c == '\'' && OPEN_QUOTE == "'")
                {
                    OPEN_QUOTE = "";
                }
                else if (c == '"' && OPEN_QUOTE == '"'.ToString())
                {
                    OPEN_QUOTE = "";
                }
                else if (c == '\'' && OPEN_QUOTE == "")
                {
                    OPEN_QUOTE = "'";
                }
                else if (c == '"' && OPEN_QUOTE == "")
                {
                    OPEN_QUOTE = '"' + "";
                }
                else if (OPEN_QUOTE != "")
                    ;
                else if (c == ';')
                {
                    new_lines.Add(tmp);
                    tmp = "";
                }
                else
                    tmp = tmp + c;
            }
            new_lines.Add(tmp);
        }

        private void new_label()
        {
            if (para_lines > max_para_lines)
            {
                para_lines -= max_para_lines;
                T_PARA += para_lines;
                Code_review_errors.Add(line_no + " : MAX para lines ");
            }

            para_lines = 0;
            T_LABEL++;
        }

        private void count_Comments(string STATEMENT)
        {
            if (STATEMENT.Split(' ').Length > 2 && first_code_line)
                T_COMMENT++;
        }

        private void analyse_code(string STATEMENT)
        {
            string nest_word = "";
            first_code_line = true;
            string[] words;
            words = STATEMENT.Split(" ".ToCharArray());
            foreach (string word in words)
            {
                if (nest_start.Contains(word))
                {
                    nest_word = word;
                    nest_lvl++;
                    if (nest_lvl > max_nest)
                    {
                        T_NEST++;
                        Code_review_errors.Add(line_no + " : Max Nest Level.");
                    }
                }
                else if (nest_end.Contains(word))
                {
                    nest_word = "";
                    nest_lvl--;
                    if (nest_lvl == 0)
                    {
                        if (nest_lines > max_nest_lines)
                        {
                            T_NEST_LINES += nest_lines;
                            Code_review_errors.Add(line_no + " : Max Nest Lines.");
                        }

                        nest_lines = 0;
                    }
                }
                else if (nest_word != "" && nest_terminators.Contains(nest_word))
                {
                    nest_lvl--;
                    nest_word = "";
                    T_NON_STANDARD++;
                    Code_review_errors.Add(line_no + " : Same Line.");
                }

                if (word == "GOTO" && nest_word != "LOCKED")
                {
                    T_GOTO++;
                    Code_review_errors.Add(line_no + " : GOTO shouln't be used.");
                    //Code_review_errors.Add("Line:" + line_no + " GOTO should not be used.");
                }
                else if (word == "CONVERT")
                    Code_review_errors.Add(line_no + " : CHANGE should be used instead of CONVERT");
            }

            if (nest_lvl > 0)
                nest_lines++;

            T_CODE += 1;
            para_lines += 1;
        }

        private void finalise_Rating()
        {
            if (T_CODE > max_code_lines)
            {
                T_CODE = T_CODE - max_code_lines;
                RATING += T_CODE * W_SIZE;
            }
            else
                T_CODE = 0;

            RATING += T_COMMENT * W_COMMENTS;
            RATING += T_GOTO * W_GOTO;
            RATING += T_PARA * W_PARA;
            RATING += T_LABEL * W_LABEL;
            RATING += T_NEST * W_NEST;
            RATING += T_NEST_LINES * W_NEST_LINES;
            RATING += T_NON_STANDARD * W_NON_STANDARD;
        }

        private void Code_Review_Report()
        {
            code_Report[0] = "CodeLines " + "\t" + "--> Lines greater than code max (" + max_code_lines + ")  \t" + T_CODE * W_SIZE;
            code_Report[1] = "ParaLines " + "\t" + "--> Lines greater than paragraph max (" + max_para_lines + ")  \t" + T_PARA * W_PARA;
            code_Report[2] = "Nests     " + "\t\t" + "--> Nested conditions greater than max (" + max_nest + ")  \t" + T_NEST * W_NEST;
            code_Report[3] = "Conditions" + "\t" + "--> Condition lines greater than max (" + max_nest_lines + ")  \t" + T_NEST_LINES * W_NEST_LINES;
            code_Report[4] = "Gotos     " + "\t\t" + "--> GOTOs (not in LOCKED clause) \t\t" + T_GOTO * W_GOTO;
            code_Report[5] = "SameLine  " + "\t" + "--> Code on same line as THEN/ELSE \t\t" + T_NON_STANDARD * W_NON_STANDARD;
            code_Report[6] = "Labels    " + "\t\t" + "--> Number of labels \t\t\t" + T_LABEL * W_LABEL;
            code_Report[7] = "Comments  " + "\t" + "--> Number of comments \t\t\t" + T_COMMENT * W_COMMENTS;
            code_Report[8] = "Rating    " + "\t\t" + "--> Overall Rating \t\t\t\t" + RATING;
        }

        #endregion code review

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.Save();

            if (Areas.Count <= 0)
                return;
            using (XmlWriter writer = XmlWriter.Create(fi.DirectoryName + "\\Env.xml"))
            {
                writer.WriteStartDocument();
                writer.WriteStartElement("Environments");

                foreach (Area a in Areas)
                {
                    writer.WriteStartElement("Area");

                    writer.WriteElementString("Name", a.AreaName);
                    writer.WriteElementString("IP", a.Ip);
                    writer.WriteElementString("Username", a.Username);
                    writer.WriteElementString("Password", a.Password);

                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
                writer.WriteEndDocument();
            }
        }

        private void preferencesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Preferences pf = new Preferences();
            pf.ShowDialog();
        }

        private void sortToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int end = ActiveDocument.Scintilla.Selection.Range.EndingLine.Number;
            int strt = ActiveDocument.Scintilla.Selection.Range.StartingLine.Number;
            string[] lines = new string[end - strt + 1];

            for (int i = strt, j = 0; i <= end; i++, j++)
                lines[j] = ActiveDocument.Scintilla.Lines[i].Text;

            Array.Sort(lines);

            ActiveDocument.Scintilla.Selection.Clear();
            for (int i = strt, j = 0; i <= end; i++, j++)
                ActiveDocument.Scintilla.InsertText(lines[j]);
        }

        private void environmentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Environments env = new Environments(Areas);
            env.ShowDialog();
            Areas = env.Areas;
            update_Env_List();
        }

        void update_Env_List()
        {
            foreach (Area a in Areas)
            {
                toolStripComboBox1.Items.Add(a.AreaName);
            }
        }

        void Read_Env_file()
        {
            try
            {
                XDocument xmlDoc = XDocument.Load(fi.DirectoryName + "\\Env.xml");

                Areas = (from a in xmlDoc.Descendants("Area")
                         select new Area
                         {
                             AreaName = a.Element("Name").Value,
                             Ip = a.Element("IP").Value,
                             Username = a.Element("Username").Value,
                             Password = a.Element("Password").Value
                         }).ToList();
            }
            catch (Exception)
            {
                // MessageBox.Show(ex.Message);
            }
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            string str = toolStripComboBox1.SelectedItem.ToString();
            if (str != "" && toolStripComboBox1.Items.Count > 0)
            {
                foreach (Area a in Areas)
                    if (a.AreaName == str)
                    {
                        Process.Start(Properties.Settings.Default.Putty, "-ssh " + a.Username + "@" + a.Ip + " -pw " + a.Password);
                        return;
                    }
            }
        }


        #region code indentation
        struct CalcCompleteStruct
        {
            public string Name;
            public int CI, NI;
            public CalcCompleteStruct(string name, int ci, int ni)
            {
                this.Name = name;
                this.CI = ci;
                this.NI = ni;
            }
        }

        struct CalcFirstStruct
        {
            public string Name;
            public int CI, NI;
            public int Special, CI2, NI2;

            public CalcFirstStruct(string name, int ci, int ni, int spec, int ci2, int ni2)
            {
                this.Name = name;
                this.CI = ci;
                this.NI = ni;
                this.Special = spec;
                this.CI2 = ci2;
                this.NI2 = ni2;
            }
        }

        struct CalcLastStruct
        {
            public string Name;
            public int CI, NI;
            public CalcLastStruct(string name, int ci, int ni)
            {
                this.Name = name;
                this.CI = ci;
                this.NI = ni;
            }
        }


        private void codeIndentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CalcCompleteStruct[] CalcCompleteAlternateCase = new CalcCompleteStruct[]{	
                                                              new CalcCompleteStruct("BEGIN CASE" , 0 , 2 ),
                                                              new CalcCompleteStruct("END CASE" , -2 , -2 ),
                                                              new CalcCompleteStruct( "END", -1, -1 ),	
                                                              new CalcCompleteStruct( "END ELSE", -1, 0 ),
                                                              new CalcCompleteStruct( "END THEN", -1, 0 ),
                                                              new CalcCompleteStruct( "LOOP", 0, 1 ),
                                                              new CalcCompleteStruct( "REPEAT", -1, -1 )
                                                              };
            CalcCompleteStruct[] CalcComplete = new CalcCompleteStruct[]{
	                                                          new CalcCompleteStruct( "BEGIN CASE", 0, 1 ),
	                                                          new CalcCompleteStruct( "END CASE", -1, -1 ),
	                                                          new CalcCompleteStruct( "END", -1, -1 ),
	                                                          new CalcCompleteStruct( "END ELSE", -1, 0 ),
	                                                          new CalcCompleteStruct( "END THEN", -1, 0 ),
	                                                          new CalcCompleteStruct( "LOOP", 0, 1 ),
	                                                          new CalcCompleteStruct( "REPEAT", -1, -1 )
                                                              };
            CalcFirstStruct[] CalcFirst = new CalcFirstStruct[]{
	                                                          new CalcFirstStruct( "CASE",  -1, 0, 0, 0, 0 ),
	                                                          new CalcFirstStruct( "FOR",  0, 1, 1, 0, 0 ),
	                                                          new CalcFirstStruct( "NEXT",  -1, -1, 0, 0, 0 ),
	                                                          new CalcFirstStruct( "LOOP",  0, 1, 2, 0, 0 ),
	                                                          new CalcFirstStruct( "WHILE",  -1, 0, 3, -1, -1 ),
	                                                          new CalcFirstStruct( "UNTIL",  -1, 0, 3, -1, -1 ),
	                                                          new CalcFirstStruct( "END",  -1, -1, 0, 0, 0 )
                                                              };

            CalcLastStruct[] CalcLast = new CalcLastStruct[]{
	                                                        new CalcLastStruct( "THEN", 0, 1 ),
	                                                        new CalcLastStruct( "ELSE",  0, 1 ),
	                                                        new CalcLastStruct( "LOCKED",  0, 1 ),
	                                                        new CalcLastStruct( "ERROR",  0, 1 )		/* Okay, should be 'ON ERROR' but we get the same result */
                                                            };

            StringBuilder sb = new StringBuilder();
            int CI = 1;
            int NI = 1;

            foreach (Line line in ActiveDocument.Scintilla.Lines)
            {
                CI = NI;
                string y_line = line.Text.Trim();

                if (y_line == "" || y_line[0] == '*' || y_line[0] == '!' || (y_line.Length > 3 && y_line.Substring(0, 3) == "REM"))
                {
                    sb.AppendLine(y_line);
                    continue;
                }
                // indentation for complete words
                foreach (CalcCompleteStruct c in CalcComplete)
                {
                    if (c.Name.Equals(y_line))
                    {
                        CI += c.CI;
                        NI += c.NI;
                        //  sb.AppendFormat("{0," + CI * 3 + "}", y_line);
                        goto FinalEnd;
                    }
                }
                // to be done from here....

                //split line to words.
                string[] cur_lin_words = y_line.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                string first_Str = cur_lin_words[0];
                string last_Str = cur_lin_words[cur_lin_words.Length - 1];

                if (first_Str == last_Str && first_Str[first_Str.Length - 1] == ':')
                {
                    sb.AppendLine(y_line);
                    continue;
                }
                // Look for cases where the LAST word is defined
                foreach (CalcLastStruct c in CalcLast)
                {
                    if (c.Name.Equals(last_Str))
                    {
                        CI += c.CI;
                        NI += c.NI;
                        goto FinalEnd;
                    }
                }

                string Ptr1 = "";// Ptr2 = "";
                //Look for cases where the FIRST word is defined
                foreach (CalcFirstStruct c in CalcFirst)
                {
                    if (c.Name.Equals(first_Str))
                    {
                        if (c.Special != 0)
                        {
                            switch (c.Special)
                            {
                                case 1:	/* FOR statement seen, look for NEXT in code */
                                    Ptr1 = "NEXT";
                                    break;
                                case 2:	/* LOOP statement seen, look for REPEAT in code */
                                case 3:	/* WHILE or UNTIL seen, loook for REPEAT in code */
                                    Ptr1 = "REPEAT";
                                    break;
                                default:
                                    Ptr1 = "";
                                    break;
                            }
                            /*      The pointer at 'Ptr1' (with length 'i1') has a word such as 'NEXT' or 'REPEAT'.
				   If the word is exactly the same as the last word, or the word is found in the
				   entire line (but surrounded by ' '), then we add the the offsets
				   at CI2 and NI2. If NOT found, we add the offsets as normal at CI and SI */
                            bool Found = false;	/* Default to not found */
                            if (last_Str == Ptr1)
                            {
                                /*      Word was found as the last word */
                                Found = true;
                            }
                            else
                            {
                                /* Look through entire structure for the word at Ptr1, which
                                   begins with ' ' , then Ptr1 , then ' ' */
                                //Ptr2 = CodexPtr, i2 = CodexLen;
                                //while (i2--)
                                //{
                                //    if (*(Ptr2++) == ' ')
                                //    {
                                //        if (memcmp (Ptr2, Ptr1, i1) == 0 && (*(Ptr2 + i1)) == ' ')
                                //        {
                                //            Found = 1;
                                //            break;
                                //        }
                                //    }
                                //}
                            }
                            if (Found)
                            {
                                CI += c.CI2;
                                NI += c.NI2;
                            }
                            else
                            {
                                CI += c.CI;
                                NI += c.NI;
                            }
                        }
                        else
                        {
                            CI += c.CI;
                            NI += c.NI;
                        }
                        goto FinalEnd;
                    }
                }
            FinalEnd:
                {
                    sb.AppendLine(string.Format("{0," + ((CI * 4) + y_line.Length) + "}", y_line));
                }
            }
            ActiveDocument.Scintilla.Text = sb.ToString();
        }

        #endregion code indentation

    }
}
